﻿Public Class Simplex
    Dim arreglo(,) As String
    Dim arreglo_temporal(,) As String
    Dim arreglo_transpuesto(,) As String
    Dim Vector_solucion() As Double
    Dim Vector_2_Auxiliar() As Double
    Dim indice() As Double
    Dim indice1() As Double
    Dim pivote As Single = 0
    Dim coef_pivotal As Single = 0
    Dim temp As Single = 0, valor
    Dim variable As Integer = 0, restricciones = 0, indiceY = 0, indiceX = 0
    Dim subY As Integer = 0
    Dim subY1 As Integer = 0
    Dim subX As Integer = 0
    Dim subX1 As Integer = 0
    Dim holguras1 As Integer = 0, artificiales1 = 0
    Dim tipo As String = "", M = "20000"
    Private multiple As Boolean = False, Artificial = False, Solucion_infinita = False, usoDual = False

    Private Sub btnCrear_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCrear.Click
        Try
            variable = Convert.ToInt16(txtVariables.Text)
            restricciones = Convert.ToInt16(txtRestricc.Text)

        Catch ex As Exception
            MessageBox.Show("Digite números", "Error")
            txtVariables.Text = ""
            txtRestricc.Text = ""

        End Try
        If variable = 1 And restricciones = 1 Then

            MessageBox.Show("Debe ingresar almenos 2 restricciones", "Error Casual")
            nuevo()
        Else

            GenerarTitulos(variable)

        End If
    End Sub

    Private Sub btnIngresar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnIngresar.Click
        Dim valor1 As String = Nothing
        Dim texto As String = Nothing

        Try
            Verificar_y_Dimensionar_Primal()
            texto = tipo
            valor1 = ""
            For y As Integer = 0 To (variable + holguras1 + artificiales1) - 1

                Vector_solucion(y) = 0
                Vector_2_Auxiliar(y) = 0

            Next

            Try
                For i As Integer = 1 To variable

                    valor1 = InputBox("Ingrese X" & i)
                    'Vector solucion de la funcion objetivo
                    Vector_solucion(i - 1) = Convert.ToDouble(valor1)
                    Vector_2_Auxiliar(i - 1) = Vector_solucion(i - 1)
                    texto = texto + (" +  " & valor1 & "X" & i)

                Next
                setMultiple(False)
                lblEtiqueta.Text = texto
                btnCalcularPrimal.Enabled = True

            Catch ex As Exception
                MessageBox.Show("Error digite bien!")


            End Try
            If Artificial Then

                For y As Integer = (holguras1 + variable) To (variable + holguras1 + artificiales1) - 1
                    Vector_solucion(y) = Convert.ToDouble(M) 'Si es dual agregar los Ms
                    Vector_2_Auxiliar(y) = Vector_solucion(y)
                Next

            End If
            For y As Integer = 0 To (variable + holguras1 + artificiales1) - 1

                Console.WriteLine(" Vector " & Vector_solucion(y))

            Next

        Catch ex As Exception
            MessageBox.Show("Tipee en tabla", "Error de ingreso")

        End Try
    End Sub

    Private Sub Rmax_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Rmax.CheckedChanged
        tipo = "Max"
        btnIngresar.Enabled = True
    End Sub

    Private Sub Rmin_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Rmin.CheckedChanged
        tipo = "Min"
        btnIngresar.Enabled = True
    End Sub

    Private Sub btnCalcularPrimal_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCalcularPrimal.Click
        setMultiple(False)
        LlenarDatosTabla()
        Try
            'LlenarDatosTabla()
        Catch ex As Exception
            MessageBox.Show("Llene los datos de la tabla", "Error de Tabla")

        End Try
        If Solucion_infinita Then

            MessageBox.Show("Soluciones Infinitas")
        End If
        If isMultiple() Then
            MessageBox.Show("Es degenarada.. Se mostrara el 1° Tablero")
        End If
        Dim oFrm As New Resultado_Primal(arreglo, variable, restricciones, tipo, holguras1, artificiales1)
        oFrm.Show()
        btnCalcularDual.Enabled = True
        btnCalcularPrimal.Enabled = False
    End Sub
    Private Sub LlenarDatosTabla()
        If ValidarCampos() Then

            MessageBox.Show("Debe existir <= , >= o =", "Error de usuario")

        End If
        Asignar_Primal()
        'System.out.println(holguras1 & " otra es " & artificiales1);
        Trabajar_Simplex(arreglo, variable, restricciones)
        Tablero_Iterativo()

    End Sub
    Public Sub Asignar_Primal()
        Dim contador As Integer = 3 + variable
        Dim contador2 As Integer = 3 + variable + holguras1
        For i As Integer = 0 To restricciones - 1
            If Tabla(variable, i).Value.Equals(">=") Then
                Datos_menos_Holgura_mas_Artificial(i, variable, contador, contador2)
                contador = contador + 1
                contador2 += 1

            ElseIf Tabla(variable, i).Value.Equals("<=") Then
                Datos_mas_Holgura(i, variable, contador)
                contador = contador + 1

            End If
        Next
        Console.WriteLine(" Tablero inicial ")
        For u As Integer = 0 To (restricciones) - 1

            For y As Integer = 0 To (3 + variable + holguras1 + artificiales1) - 1

                Console.Write(arreglo(u, y) & " ")

            Next
            Console.WriteLine(" ")
        Next
    End Sub
    Public Sub Datos_menos_Holgura_mas_Artificial(ByVal i, ByVal variable, ByVal contador, ByVal contador2)
        For j As Integer = 3 To (variable + 3) - 1
            arreglo(i, j) = Tabla(j - 3, i).Value.ToString
        Next
        arreglo(i, contador) = "-1"
        arreglo(i, contador2) = "1"
        arreglo(i, 2) = Tabla(variable + 1, i).Value.ToString
        arreglo(i, 1) = "L" & i
        arreglo(i, 0) = M
    End Sub
    Public Sub Datos_mas_Holgura(ByVal i, ByVal variable, ByVal contador)
        For j As Integer = 3 To (variable + 3) - 1
            arreglo(i, j) = Tabla(j - 3, i).Value.ToString
        Next
        arreglo(i, contador) = "1"
        arreglo(i, 2) = Tabla(variable + 1, i).Value.ToString
        arreglo(i, 1) = "X" & (i + variable + 1)
        arreglo(i, 0) = "0"
    End Sub
    Private Sub Tablero_Iterativo()


    End Sub

    Private Sub Trabajar_Simplex(ByVal arreglo_interno As String(,), ByVal columna As Integer, ByVal filas As Integer)
        Llenarzj_cj(arreglo_interno, columna, filas)
        indiceY = Procesar_IndiceY(indice, arreglo_interno)
        Console.WriteLine("Indice Y " & indiceY.ToString)
        valor = Convert.ToDouble(arreglo_interno(filas, indiceY))
        Console.WriteLine(" Menor valor " & valor.ToString)
        While valor < 0
            '/////////////// Inicia Obtener pivote,indiceX,y coef pivotal
            For z As Integer = 0 To filas - 1
                Dim a As Double = 0
                indice1(z) = Convert.ToDouble(arreglo_interno(z, 2)) / Convert.ToDouble(arreglo_interno(z, indiceY))
                a = indice1(z)
                If Double.IsInfinity(a) Then
                    indice1(z) = 1000000000
                End If
                'Console.WriteLine(indice1(z).ToString)
            Next
            indiceX = Procesar_IndiceX(indice1, 1)
            Console.WriteLine("indice X " & indiceX.ToString)
            pivote = Convert.ToDouble(arreglo_interno(indiceX, indiceY))
            Console.WriteLine("pivote " & pivote.ToString)
            coef_pivotal = Convert.ToDouble(arreglo_interno(indiceX, 2)) / pivote
            Console.WriteLine("coef pivotal" & coef_pivotal.ToString)
            If coef_pivotal <= 0 Then
                Solucion_infinita = True
                Exit While
            End If
            '//////////////// Finaliza Obtener pivote,indiceX,y coef pivotal

            '//////////////////Inicia Rellenar nueva fila pivote
            arreglo_temporal(indiceX, 0) = Vector_solucion(indiceY - 3).ToString
            Console.WriteLine(" in 0 " & arreglo_temporal(indiceX, 0))
            arreglo_temporal(indiceX, 1) = "X" & (indiceY - 2)
            Console.WriteLine(" in 1 " & arreglo_temporal(indiceX, 1))
            arreglo_temporal(indiceX, 2) = coef_pivotal.ToString
            Console.WriteLine(" in 2 " & arreglo_temporal(indiceX, 2))
            For h As Integer = 3 To (3 + columna + holguras1 + artificiales1) - 1
                arreglo_temporal(indiceX, h) = (Convert.ToDouble(arreglo_interno(indiceX, h)) / pivote).ToString
                Console.WriteLine("nueva fila pivote " & arreglo_temporal(indiceX, h))
            Next
            '///////////////// Finaliza Rellenar nueva fila pivote

            For m As Integer = 0 To filas - 1
                If m <> indiceX Then
                    arreglo_temporal(m, 0) = arreglo_interno(m, 0) 'Primeros xk,ck
                    Console.WriteLine(" Xs ant " & arreglo_temporal(indiceX, 0))
                    arreglo_temporal(m, 1) = arreglo_interno(m, 1)
                    Console.WriteLine(" Xs ant " & arreglo_temporal(indiceX, 1))
                    arreglo_temporal(m, 2) = (Convert.ToDouble(arreglo_interno(m, 2)) - Convert.ToDouble(arreglo_interno(m, indiceY)) * coef_pivotal).ToString
                    Console.WriteLine(" Nuevo Bi " & arreglo_temporal(indiceX, 2))
                    Dim semipivote As Double = Convert.ToDouble(arreglo_interno(m, indiceY))
                    For n As Integer = 3 To (3 + columna + holguras1 + artificiales1) - 1

                        arreglo_temporal(m, n) = (Convert.ToDouble(arreglo_interno(m, n)) - semipivote * Convert.ToDouble(arreglo_temporal(indiceX, n))).ToString
                        Console.WriteLine("Nueva fila " & arreglo_temporal(m, n))
                    Next

                End If
            Next
            Llenarzj_cj(arreglo_temporal, columna, filas)
            indiceY = Procesar_IndiceY(indice, arreglo_temporal)
            valor = Convert.ToDouble(arreglo_temporal(filas, indiceY))
            Console.WriteLine(" Menor valor " & valor.ToString)
            arreglo_interno = arreglo_temporal

        End While
        arreglo = arreglo_interno
    End Sub
    Public Function Procesar_IndiceX(ByVal indice11 As Double(), ByVal i As Integer) As Integer
        Dim valors As Integer = 0
        subX = Obtener_Indice(indice11, i)
        subX1 = Obtener_Indice1(indice11, i)
        If subX = subX1 Then
            valors = subX
        Else
            valors = subX
            setMultiple(True)
        End If
        Return valors
    End Function

    Public Function BuscarXs(ByVal subh As Integer, ByVal arreglo As String(,)) As Boolean
        Dim resultado As Boolean = False
        Dim numero As Integer = subh + 1
        For k As Integer = 0 To restricciones - 1
            If arreglo(k, 1) = "X" & numero.ToString Then
                resultado = True
            End If
        Next
        Return resultado
    End Function
    Public Function Procesar_IndiceY(ByVal indicep As Double(), ByVal arreglo_interno As String(,)) As Integer
        Dim valors As Integer = 0
        subY = Obtener_Indice(indicep, -1)
        subY1 = Obtener_Indice1(indicep, -1)
        If subY = subY1 Then
            valors = subY + 3
        ElseIf BuscarXs(subY1, arreglo) = False Then

            valors = subY + 3

        ElseIf BuscarXs(subY, arreglo) = False Then

            valors = subY1 + 3
        End If
        Return valors
    End Function
    Public Function Obtener_Indice(ByVal indi As Double(), ByVal p As Integer) As Integer
        If p = 0 Then
            For i As Integer = 0 To indi.Length - 1
                If indi(i) < 0 Then
                    indi(i) = 1999999999
                End If
            Next
        End If
        Dim b As Integer = 0
        For i As Integer = 0 To indi.Length - 1
            If indi(i) < indi(b) Then
                b = i
            End If
        Next
        Return b
    End Function
    Public Function Obtener_Indice1(ByVal indi As Double(), ByVal p As Integer) As Integer
        If p = 0 Then
            For i As Integer = 0 To indi.Length - 1
                If indi(i) < 0 Then
                    indi(i) = 1999999999
                End If
            Next
        End If
        Dim b As Integer = 0
        Dim b2 As Integer = 0
        For i As Integer = 0 To indi.Length - 1
            If indi(i) < indi(b) Then
                b = i
                b2 = b
            End If
            If indi(i) = indi(b2) Then
                b2 = i
            End If
        Next
        Return b2
    End Function
    Public Sub Llenarzj_cj(ByVal arreglo1, ByVal columna, ByVal filas)
        For a As Integer = 3 To (3 + columna + holguras1 + artificiales1) - 1
            temp = 0
            For k As Integer = 0 To filas - 1

                temp = temp + Convert.ToDouble(arreglo1(k, 0)) * Convert.ToDouble(arreglo1(k, a))
            Next
            If Rmax.Checked And usoDual Then
                temp = Vector_solucion(a - 3) - temp
            ElseIf Rmin.Checked And usoDual Then
                temp = temp - Vector_solucion(a - 3)
            ElseIf Rmax.Checked Then
                temp = temp - Vector_solucion(a - 3)
            ElseIf Rmin.Checked Then
                temp = Vector_solucion(a - 3) - temp
            End If
            Console.WriteLine(" Zj-Cj " & temp.ToString)
            indice(a - 3) = temp
            arreglo1(filas, a) = temp.ToString
        Next
    End Sub

    Private Function ValidarCampos() As Boolean
        Dim valido As Boolean = False
        For i As Integer = 0 To restricciones - 1
            If Tabla(variable, i).Value.Equals(">=") OrElse Tabla(variable, i).Value.Equals("<=") OrElse Tabla(variable, i).Value.Equals("=") Then
                valido = False
            Else
                valido = True
            End If
        Next
        Return valido
    End Function

    Private Sub btnCalcularDual_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCalcularDual.Click
        If Rmin.Checked Then
            MessageBox.Show("No programado para minimizacion", "Casualidad")
        Else
            usoDual = True
            Verificar_y_Dimensionar_Dual()
            Asignar_Dual()
            Trabajar_Simplex(arreglo_transpuesto, restricciones, variable)
        End If
        If Solucion_infinita Then
            MessageBox.Show("Soluciones Infinitas", "Casualidad")
        End If
        Dim oFrm As New Resultado_Dual(arreglo, variable, tipo, restricciones, artificiales1, holguras1)
        oFrm.Show()
        btnCalcularDual.Enabled = False
        btnIngresar.Enabled = False
    End Sub
    Public Sub Verificar_y_Dimensionar_Dual()
        Dim holguras As Integer = 0
        Dim artificiales As Integer = 0
        For i As Integer = 0 To variable - 1
            holguras += 1 'Validamos restricciones
            artificiales += 1
            Artificial = True
        Next

        Dim nuevoF1 As Integer = 3 + holguras + artificiales + restricciones
        Dim nuevoF2 As Integer = variable + 1
        ReDim indice(0 To (holguras + artificiales + restricciones) - 1)
        ReDim indice1(0 To variable - 1)
        ReDim arreglo_transpuesto(0 To nuevoF2, nuevoF1 - 1)
        ReDim arreglo_temporal(0 To nuevoF2, nuevoF1 - 1)
        ReDim Vector_solucion(0 To nuevoF1 - 3 - 1)
        Llenar0s((holguras + artificiales), restricciones, variable, arreglo_transpuesto)
        holguras1 = holguras
        artificiales1 = artificiales

    End Sub
    Public Sub Asignar_Dual()
        'Dualizar es con minimizacion
        Dim contador As Integer = 3 + restricciones
        Dim contador2 As Integer = 3 + restricciones + holguras1
        For i As Integer = 0 To variable - 1
            Datos_menos_Holgura_mas_ArtificialT(i, restricciones, contador, contador2) 'Validamos restricciones
            contador = contador + 1
            contador2 += 1

        Next
        'asignar nuevo vector solucion
        For a As Integer = 0 To restricciones - 1
            'Esto transfiere los valores al nuevo vector solucion
            Vector_solucion(a) = Convert.ToDouble(Tabla(variable + 1, a).Value)
        Next
        For y As Integer = (holguras1 + restricciones) To (restricciones + holguras1 + artificiales1) - 1
            Vector_solucion(y) = Convert.ToDouble(M)
        Next


    End Sub
    Public Sub Datos_menos_Holgura_mas_ArtificialT(ByVal i As Integer, ByVal columna As Integer, ByVal contador As Integer, ByVal contador2 As Integer)
        For j As Integer = 3 To (columna + 3) - 1
            arreglo_transpuesto(i, j) = Tabla(i, (j - 3)).Value.ToString
        Next
        arreglo_transpuesto(i, 2) = Vector_2_Auxiliar(i)
        arreglo_transpuesto(i, 1) = "L" & i
        arreglo_transpuesto(i, 0) = M
        arreglo_transpuesto(i, contador) = "-1"
        arreglo_transpuesto(i, contador2) = "1"
    End Sub
    Private Sub GenerarTitulos(ByVal variable As Integer)
        Tabla.ColumnCount = variable + 2
        Tabla.RowCount = restricciones
        For i As Integer = 0 To variable - 1

            Tabla.Columns(i).Name = "X" & Convert.ToString(i + 1)

        Next
        Tabla.Columns(variable).Name = "Signo"
        Tabla.Columns(variable + 1).Name = "Valor"
        Tabla.ColumnHeadersVisible = True

    End Sub

    Private Sub Verificar_y_Dimensionar_Primal()
        Dim holguras As Integer = 0
        Dim artificiales As Integer = 0
        For i As Integer = 0 To restricciones - 1
            If Tabla(variable, i).Value.Equals(">=") Then

                holguras += 1 'Validamos restricciones
                artificiales += 1
                Artificial = True
            ElseIf Tabla(variable, i).Value.Equals("<=") Then

                holguras += 1
            End If
        Next

        Dim nuevoF1 As Integer = 3 + variable + holguras + artificiales
        Dim nuevoF2 As Integer = restricciones + 1
        ReDim arreglo(0 To nuevoF2 - 1, 0 To nuevoF1 - 1)
        ReDim arreglo_temporal(0 To nuevoF2 - 1, 0 To nuevoF1 - 1)
        ReDim Vector_solucion(0 To nuevoF1 - 3 - 1)
        ReDim Vector_2_Auxiliar(0 To nuevoF1 - 3 - 1)
        ReDim indice(0 To (variable + holguras + artificiales) - 1)
        ReDim indice1(0 To restricciones - 1)
        Llenar0s((holguras + artificiales), variable, restricciones, arreglo)
        holguras1 = holguras
        artificiales1 = artificiales

    End Sub
    Private Sub Llenar0s(ByVal valores As Integer, ByVal columna As Integer, ByVal filas As Integer, ByVal arreglo As String(,))
        For i As Integer = 0 To filas - 1
            For h As Integer = (columna + 3) To (columna + valores + 3) - 1

                arreglo(i, h) = "0" 'Rellenando con 0's
            Next
        Next

    End Sub

    Private Sub setMultiple(ByVal p As Boolean)
        multiple = p

    End Sub
    Public Function isMultiple()
        Return multiple
    End Function

    Private Sub nuevoToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles nuevoToolStripMenuItem.Click
        nuevo()
    End Sub

    Private Sub salirToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles salirToolStripMenuItem.Click
        End
    End Sub
    Public Sub nuevo()
        txtRestricc.Text = ""
        txtVariables.Text = ""
        btnCalcularPrimal.Enabled = False
        btnIngresar.Enabled = False
        btnCrear.Enabled = True
    End Sub

    Private Sub AcercaDEToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AcercaDEToolStripMenuItem.Click
        AcercaDE.Show()
    End Sub
End Class
